/*
 * Copyright 2022 The Open Islands Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.openislands.oi.util;

import org.openislands.oi.constant.Dict;
import org.openislands.oi.rpc.base.RouteNode;
import org.springframework.core.env.PropertySource;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;

public class ConfiguratorUtils {
    private static final Properties props;
    private static final String contextPathSuffix = ".server.servlet.context-path";
    private static final Map<String, String[][]> serviceRouteCache = new HashMap<>();

    public static String contextPath(String serviceMark) {
        Object contextPath = ConfiguratorUtils.get(serviceMark + contextPathSuffix);
        return contextPath != null ? contextPath.toString() : "";
    }

    public static RouteNode serviceRoute(String serviceMark) {
        if (serviceRouteCache.isEmpty()) {
            loadServiceRoute();
        }
        String[][] routes = serviceRouteCache.get(serviceMark);
        RouteNode routeNode = new RouteNode();
        routeNode.setHttpAccess(routes[0][0] + ":" + routes[0][1]);
        routeNode.setGrpcAccess(routes[0][0] + ":" + routes[0][2]);
        return routeNode;
    }

    public static synchronized void loadServiceRoute() {
        String[] serviceMark = {Dict.MASTER_MARK, Dict.WORKER_MARK, Dict.FEDERATED_PROXY_MARK};
        String[] suffix = {".host", ".http_port", ".grpc_port"};
        for (String mark : serviceMark) {
            String[] route = new String[suffix.length];
            for (int i = 0; i < suffix.length; i++) {
                String key = mark + suffix[i];
                route[i] = Objects.requireNonNull(props.get(key), key + " is null").toString();
            }
            serviceRouteCache.put(mark, new String[][]{route});
        }
    }

    public static Properties getProperties() {
        return props;
    }

    public static Object get(Object key) {
        return props.get(key);
    }

    public static Object put(Object key, Object value) {
        return props.put(key, value);
    }

    public static void put(Map<Object, Object> map) {
        props.putAll(map);
    }

    static {
        props = new Properties();

        String[] serviceMark = {Dict.APISERVER_MARK, Dict.MASTER_MARK, Dict.WORKER_MARK};
        String[] serviceConfig = {Dict.APISERVER_CONFIG_FILE, Dict.MASTER_CONFIG_FILE, Dict.WORKER_CONFIG_FILE};
        for (int i = 0; i < serviceMark.length; i++) {
            try {
                PropertySource<?> propertySource = YamlUtils.loadYamlSource(serviceConfig[i]);
                Object property = propertySource.getProperty("server.servlet.context-path");
                assert property != null;
                props.setProperty(serviceMark[i] + contextPathSuffix, property.toString());
            } catch (IOException ignored) {
            }
        }
    }
}
